//C03:ichar_traits.h
// Creating your own character traits.
#ifndef ICHAR_TRAITS_H
#define ICHAR_TRAITS_H
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstddef>
#include <memory>
#include <ostream>
#include <string>
using std::allocator;
using std::basic_string;
using std::char_traits;
using std::ostream;
using std::size_t;
using std::string;
using std::toupper;
using std::tolower;

struct ichar_traits : char_traits<char> {
  // We'll only change character-by-
  // character comparison functions
  static bool eq(char c1st, char c2nd) {
    return toupper(c1st) == toupper(c2nd);
  }

  static bool ne(char c1st, char c2nd) {
    return !eq(c1st, c2nd);
  }

  static bool lt(char c1st, char c2nd) {
    return toupper(c1st) < toupper(c2nd);
  }

  static int compare(const char* str1, const char* str2, size_t n) {
    for(size_t i = 0; i < n; ++i) {
      if(str1 == 0) {
        return -1;
      }  
      else if(str2 == 0){
        return 1;
      }
      else if(tolower(*str1) < tolower(*str2)) {
        return -1;
      }
      else if(tolower(*str1) > tolower(*str2)) {
        return 1;
      }
      assert(tolower(*str1) == tolower(*str2));
      ++str1; // Compare the other chars
      ++str2;
    }
    return 0;
  }

  static const char* find(const char* s1, size_t n, char c) {
    while(n-- > 0) {
      if(toupper(*s1) == toupper(c)) {
        return s1;
      }
      else {
        ++s1;
      }
    }
    return 0;
  }
};

typedef basic_string<char, ichar_traits> istring;
inline ostream& operator<<(ostream& os, const istring& s) {
  return os << string(s.c_str(), s.length());  
}
#endif